//
//  NSMutableAttributedString+OFAttributedString.m
//  CCAttributedStringDemo
//
//  Created by offcn_44 on 2017/3/28.
//  Copyright © 2017年 offcn_44. All rights reserved.
//

#import "NSMutableAttributedString+OFAttributedString.h"
#import <objc/runtime.h>
#import "OFAttributedStringBuilder.h"
@interface NSMutableAttributedString ()
@property(nonatomic,strong)OFAttributedStringBuilder*attributedStringBuilder;
@end
static const void * attributedStringBuilderKey=@"attributedStringBuilder";
@implementation NSMutableAttributedString (OFAttributedString)
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.attributedStringBuilder=[[OFAttributedStringBuilder alloc]init];
    }
    return self;
}
-(OFAttributedStringBuilder*)attributedStringBuilder
{
    return objc_getAssociatedObject(self, attributedStringBuilderKey);
}
-(void)setAttributedStringBuilder:(OFAttributedStringBuilder *)attributedStringBuilder
{
    return objc_setAssociatedObject(self, attributedStringBuilderKey, attributedStringBuilder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/*
 字体颜色
 **/
-(NSMutableAttributedString*(^)(UIColor*))textColor
{
    return ^ id (UIColor *color)
    {
        self.attributedStringBuilder.currentTextColor=color;
        return self;
    };
}
/*
 背景颜色
 **/
-(NSMutableAttributedString*(^)(UIColor*))backgroundColor
{
    return ^ id (UIColor *color)
    {
        self.attributedStringBuilder.currentBackgroundColor=color;
        return self;
    };
}
/*
 字号
 **/
-(NSMutableAttributedString*(^)(UIFont*))font
{
    return ^ id (UIFont *font)
    {
        self.attributedStringBuilder.currentFont=font;
        return self;
    };
}
/*
 下划线
 **/
-(NSMutableAttributedString*(^)(NSUnderlineStyle))underline
{
    return ^ id (NSUnderlineStyle underline)
    {
        self.attributedStringBuilder.underline=@(underline);
        return self;
    };
}
/*
 下划线颜色
 **/
-(NSMutableAttributedString*(^)(UIColor*))underlineColor
{
    return ^ id (UIColor* underlineColor)
    {
        self.attributedStringBuilder.underLineColor=underlineColor;
        return self;
    };
}
/*
 描边
 **/
-(NSMutableAttributedString*(^)(UIColor*))strokeColor
{
    return ^ id (UIColor* strokeColor)
    {
        self.attributedStringBuilder.strokeColor=strokeColor;
        return self;
    };
}
/*
 描边宽度
 **/
-(NSMutableAttributedString*(^)(CGFloat))strokeWidth
{
   return ^id(CGFloat strokeWidth)
    {
        self.attributedStringBuilder.strokeWidth=@(strokeWidth);
        return self;
    };
}
/*
 斜体
 **/
-(NSMutableAttributedString*(^)(BOOL))obliqueness
{
    return ^id(BOOL obliqueness)
    {
        self.attributedStringBuilder.obliqueness=@(obliqueness);
        return self;
    };
}
/*
 扁平体
 **/
-(NSMutableAttributedString*(^)(BOOL))expansion
{
    return ^id(BOOL expansion)
    {
        self.attributedStringBuilder.obliqueness=@(expansion);
        return self;
    };
}
/*
 删除线
 **/
-(NSMutableAttributedString*(^)(BOOL))strikethrough
{
    return ^id(BOOL strikethrough)
    {
        self.attributedStringBuilder.strikethrough=@(strikethrough);
        return self;
    };
}
/*
 删除线颜色
 **/
-(NSMutableAttributedString*(^)(UIColor*))strikethroughColor
{
    return ^id(UIColor* strikethroughColor)
    {
        self.attributedStringBuilder.strikethroughColor=strikethroughColor;
        return self;
    };
}
/*
 连体
 **/
-(NSMutableAttributedString*(^)(BOOL))ligature
{
    return ^id(BOOL ligature)
    {
        self.attributedStringBuilder.ligature=@(ligature);
        return self;
    };
}
/*
 字体阴影
 **/
-(NSMutableAttributedString*(^)(NSShadow*))shadow
{
    return ^id(NSShadow* shadow)
    {
        self.attributedStringBuilder.shadow=shadow;
        return self;
    };
}
/*
 凸版印刷体
 **/
-(NSMutableAttributedString*(^)(BOOL))effectLetterpressStyle
{
    return ^id(BOOL effectLetterpressStyle)
    {
        self.attributedStringBuilder.effectLetterpressStyle=@(effectLetterpressStyle);
        return self;
    };
}
/*
 字体偏移
 **/
-(NSMutableAttributedString*(^)(CGFloat))baselineOffset
{
    return ^id(CGFloat baselineOffset)
    {
        self.attributedStringBuilder.baselineOffset=@(baselineOffset);
        return self;
    };
}
/*
 URL链接
 **/
-(NSMutableAttributedString*(^)(NSURL*))link
{
    return ^id(NSURL* link)
    {
        self.attributedStringBuilder.link=link;
        return self;
    };

}
/*
 书写方向
 **/
-(NSMutableAttributedString*(^)(id))writingDirection
{
    return ^id(id writingDirection)
    {
        self.attributedStringBuilder.writingDirection=writingDirection;
        return self;
    };
}
/*
 行间距
 **/
-(NSMutableAttributedString*(^)(CGFloat))lineSpace
{
    return ^id(CGFloat lineSpace)
    {
        [self lineSpaceWithSpace:lineSpace];
        return self;
    };
}
/*
 字间距
 **/
-(NSMutableAttributedString*(^)(CGFloat))textSpace
{
    return ^id(CGFloat textSpace)
    {
        self.attributedStringBuilder.textSpace=@(textSpace);
        return self;
    };
}
/*
 根据一串或者一组字符串添加效果
 **/
- (NSMutableAttributedString *(^)(id))rangeString
{
    return ^ id (id rangeObj)
    {
        
        void(^addBlock)(NSString *) = ^ (NSString *targetString)
        {
            if (self.attributedStringBuilder.rangeIndex)
            {
                [self addAttributesAtRangeIndexWithObj:targetString];
            }
            else if (self.attributedStringBuilder.all && [self.attributedStringBuilder.all boolValue])
            {
                [self addAttributesAllWithObj:targetString];
            }
            else
            {
                [self addAttributesWithObj:targetString];
            }
        };
        
        if ([rangeObj isKindOfClass:[NSString class]])
        {
            addBlock(rangeObj);
        }
        else if ([rangeObj isKindOfClass:[NSArray class]])
        {
            for (id obj in rangeObj)
            {
                if ([obj isKindOfClass:[NSString class]])
                {
                    self.attributedStringBuilder.isAddingInArray = !([obj isEqual:[rangeObj lastObject]]);
                    addBlock(obj);
                }
            }
        }
        return self;
    };
}

- (NSMutableAttributedString *(^)(NSRange))range
{
    return ^ id (NSRange range) {
        [self addAttributesWithRange:range];
        return self;
    };
}

- (NSMutableAttributedString * (^)(NSTextAttachment *,NSInteger))attachment
{
    return ^ id (NSTextAttachment *attachment,NSInteger index)
    {
        [self insertAttachment:attachment atIndex:index];
        return self;
    };
}

- (NSMutableAttributedString * (^)())all
{
    return ^ id {
        self.attributedStringBuilder.all = @(YES);
        return self;
    };
}
- (NSMutableAttributedString * (^)(NSInteger))rangeIndex
{
    return ^ id (NSInteger index)
    {
        self.attributedStringBuilder.rangeIndex = @(index);
        return self;
    };
}

#pragma mark - private

- (NSArray *)rangeOfSubString:(NSString *)targetString
{
    
    NSMutableArray *rangeArray = [NSMutableArray array];
    NSString *totalString = [NSString stringWithFormat:@"%@%@",self.string,targetString];
    NSString *temp;
    for (int i = 0; i < self.string.length; i ++)
    {
        temp = [totalString substringWithRange:NSMakeRange(i, targetString.length)];
        if ([temp isEqualToString:targetString])
        {
            NSRange range = {i,targetString.length};
            [rangeArray addObject:NSStringFromRange(range)];
        }
    }
    return rangeArray;
}

- (NSRange)getRangeWithObj:(NSString *)targetString
{
    return [[self string] rangeOfString:targetString options:NSCaseInsensitiveSearch];
}

- (void)addAttributesAllWithObj:(NSString *)targetString
{
    NSArray *rangeArray = [self rangeOfSubString:targetString];
    for (NSString *rangeString in rangeArray)
    {
        self.attributedStringBuilder.isAddingInArray = ![rangeString isEqual:[rangeArray lastObject]];
        NSRange range = NSRangeFromString(rangeString);
        [self addAttributesWithRange:range];
    }
    self.attributedStringBuilder.all = nil;
}

- (void)addAttributesAtRangeIndexWithObj:(NSString *)targetString
{
    NSArray *rangeArray = [self rangeOfSubString:targetString];
    NSRange range;
    if (self.attributedStringBuilder.rangeIndex.integerValue > rangeArray.count - 1)
    {
        range = NSRangeFromString([rangeArray lastObject]);
    }
    else
    {
        range = NSRangeFromString([rangeArray objectAtIndex:self.attributedStringBuilder.rangeIndex.integerValue]);
    }
    [self addAttributesWithRange:range];
    if (self.attributedStringBuilder.isAddingInArray) return;
    self.attributedStringBuilder.rangeIndex = nil;
    self.attributedStringBuilder.all = nil;
}

- (void)addAttributesWithObj:(NSString *)targetString
{
    [self textColorWithObj:targetString];
    [self textFontWithObj:targetString];
    [self backgroundColorWithObj:targetString];
    [self textObliquenessWithObj:targetString];
    [self textExpansionWithObj:targetString];
    [self textSpaceWithObj:targetString];
    [self textUnderLineWithObj:targetString];
    [self textUnderLineColorWithObj:targetString];
    [self textStrokeColorWithObj:targetString];
    [self textStrokeWidthWithObj:targetString];
    [self textStrikethroughWithObj:targetString];
    [self textStrikethroughColorWithObj:targetString];
    [self textLigatureWithObj:targetString];
    [self textShadowWithObj:targetString];
    [self textEffectLetterpressStyleWithObj:targetString];
    [self textBaselineOffsetWithObj:targetString];
    [self textWriteDirectionWithObj:targetString];
    [self textLinkWithObj:targetString];
}

- (void)addAttributesWithRange:(NSRange)range
{
    [self textColorWithRange:range];
    [self textFontWithRange:range];
    [self backgroundColorWithRange:range];
    [self textObliquenessWithRange:range];
    [self textExpansionWithRange:range];
    [self textSpaceWithRange:range];
    [self textUnderLineWithRange:range];
    [self textUnderLineColorWithRange:range];
    [self textStrokeColorWithRange:range];
    [self textStrokeWidthWithRange:range];
    [self textStrikethroughWithRange:range];
    [self textStrikethroughColorWithRange:range];
    [self textLigatureWithRange:range];
    [self textShadowWithRange:range];
    [self textEffectLetterpressStyleWithRange:range];
    [self textBaselineOffsetWithRange:range];
    [self textWriteDirectionWithRange:range];
    [self textLinkWithRange:range];
}



- (void)textColorWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.currentTextColor) return;
    [self addAttribute:NSForegroundColorAttributeName value:self.attributedStringBuilder.currentTextColor range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.currentTextColor = nil;
}

- (void)textColorWithObj:(NSString *)targetString
{
    [self textColorWithRange:[self getRangeWithObj:targetString]];
}


- (void)backgroundColorWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.currentBackgroundColor) return;
    [self addAttribute:NSBackgroundColorAttributeName value:self.attributedStringBuilder.currentBackgroundColor range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.currentBackgroundColor = nil;
}

- (void)backgroundColorWithObj:(NSString *)targetString
{
    [self backgroundColorWithRange:[self getRangeWithObj:targetString]];
}


- (void)textFontWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.currentFont) return;
    [self addAttribute:NSFontAttributeName value:self.attributedStringBuilder.currentFont range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.currentFont = nil;
}

- (void)textFontWithObj:(NSString *)targetString
{
    [self textFontWithRange:[self getRangeWithObj:targetString]];
}


- (void)textObliquenessWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.obliqueness) return;
    [self addAttribute:NSObliquenessAttributeName value:self.attributedStringBuilder.obliqueness range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.obliqueness = nil;
}

- (void)textObliquenessWithObj:(NSString *)targetString
{
    [self textObliquenessWithRange:[self getRangeWithObj:targetString]];
}


- (void)textExpansionWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.expansion) return;
    [self addAttribute:NSExpansionAttributeName value:self.attributedStringBuilder.expansion range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.expansion = nil;
}

- (void)textExpansionWithObj:(NSString *)targetString
{
    [self textExpansionWithRange:[self getRangeWithObj:targetString]];
}


- (void)lineSpaceWithSpace:(CGFloat)space
{
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineSpacing:space];
    [self addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:[self getRangeWithObj:self.string]];
}


- (void)textSpaceWithObj:(NSString *)targetString
{
    [self textSpaceWithRange:[self getRangeWithObj:targetString]];
}

- (void)textSpaceWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.textSpace) return;
    [self addAttribute:NSKernAttributeName value:self.attributedStringBuilder.textSpace range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.textSpace = nil;
}


- (void)textUnderLineWithObj:(NSString *)targetString
{
    [self textUnderLineWithRange:[self getRangeWithObj:targetString]];
}

- (void)textUnderLineWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.underline) return;
    [self addAttribute:NSUnderlineStyleAttributeName value:self.attributedStringBuilder.underline range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.underline = nil;
}


- (void)textUnderLineColorWithObj:(NSString *)targetString
{
    [self textUnderLineColorWithRange:[self getRangeWithObj:targetString]];
}

- (void)textUnderLineColorWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.underLineColor) return;
    [self addAttribute:NSUnderlineColorAttributeName value:self.attributedStringBuilder.underLineColor range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.underLineColor = nil;
}


- (void)textStrokeColorWithObj:(NSString *)targetString
{
    [self textStrokeColorWithRange:[self getRangeWithObj:targetString]];
}

- (void)textStrokeColorWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.strokeColor) return;
    [self addAttribute:NSStrokeColorAttributeName value:self.attributedStringBuilder.strokeColor range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.strokeColor = nil;
}


- (void)textStrokeWidthWithObj:(NSString *)targetString
{
    [self textStrokeWidthWithRange:[self getRangeWithObj:targetString]];
}

- (void)textStrokeWidthWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.strokeWidth) return;
    [self addAttribute:NSStrokeWidthAttributeName value:self.attributedStringBuilder.strokeWidth range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.strokeWidth = nil;
}


- (void)textStrikethroughWithObj:(NSString *)targetString
{
    [self textStrikethroughWithRange:[self getRangeWithObj:targetString]];
}

- (void)textStrikethroughWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.strikethrough) return;
    [self addAttribute:NSStrikethroughStyleAttributeName value:self.attributedStringBuilder.strikethrough range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.strikethrough = nil;
}


- (void)textStrikethroughColorWithObj:(NSString *)targetString
{
    [self textStrikethroughColorWithRange:[self getRangeWithObj:targetString]];
}

- (void)textStrikethroughColorWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.strikethroughColor) return;
    [self addAttribute:NSStrikethroughColorAttributeName value:self.attributedStringBuilder.strikethroughColor range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.strikethroughColor = nil;
}


- (void)textLigatureWithObj:(NSString *)targetString
{
    [self textStrikethroughColorWithRange:[self getRangeWithObj:targetString]];
}

- (void)textLigatureWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.ligature) return;
    [self addAttribute:NSLigatureAttributeName value:self.attributedStringBuilder.ligature range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.ligature = nil;
}


- (void)textShadowWithObj:(NSString *)targetString
{
    [self textShadowWithRange:[self getRangeWithObj:targetString]];
}

- (void)textShadowWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.shadow) return;
    [self addAttribute:NSShadowAttributeName value:self.attributedStringBuilder.shadow range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.shadow = nil;
}


- (void)textEffectLetterpressStyleWithObj:(NSString *)targetString
{
    [self textEffectLetterpressStyleWithRange:[self getRangeWithObj:targetString]];
}

- (void)textEffectLetterpressStyleWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.effectLetterpressStyle) return;
    if ([self.attributedStringBuilder.effectLetterpressStyle boolValue]) [self addAttribute:NSTextEffectAttributeName value:NSTextEffectLetterpressStyle range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.effectLetterpressStyle = nil;
}


- (void)textBaselineOffsetWithObj:(NSString *)targetString
{
    [self textBaselineOffsetWithRange:[self getRangeWithObj:targetString]];
}

- (void)textBaselineOffsetWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.baselineOffset) return;
    [self addAttribute:NSBaselineOffsetAttributeName value:self.attributedStringBuilder.baselineOffset range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.baselineOffset = nil;
}


- (void)textWriteDirectionWithObj:(NSString *)targetString
{
    [self textWriteDirectionWithRange:[self getRangeWithObj:targetString]];
}

- (void)textWriteDirectionWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.writingDirection) return;
    [self addAttribute:NSWritingDirectionAttributeName value:self.attributedStringBuilder.writingDirection range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.writingDirection = nil;
}


- (void)textLinkWithObj:(NSString *)targetString
{
    [self textLinkWithRange:[self getRangeWithObj:targetString]];
}

- (void)textLinkWithRange:(NSRange)range
{
    if (!self.attributedStringBuilder.link) return;
    [self addAttribute:NSLinkAttributeName value:self.attributedStringBuilder.link range:range];
    if (!self.attributedStringBuilder.isAddingInArray) self.attributedStringBuilder.link = nil;
}

- (void)insertAttachment:(NSTextAttachment *)attachment atIndex:(NSInteger)index
{
    NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
    [self insertAttributedString:attachmentString atIndex:index];
}


@end
